package cc.linker.steplink.crm.merchanth5.service.impl;

import cc.linker.steplink.crm.commons.FeeConstants;
import cc.linker.steplink.crm.commons.TradeTypeConstants;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.merchanth5.dao.acs.H5RechargeDao;
import cc.linker.steplink.crm.merchanth5.dao.acs.PurchaseProcessDao;
import cc.linker.steplink.crm.merchanth5.pojo.H5UserAccountPo;
import cc.linker.steplink.crm.merchanth5.pojo.acs.ProtectPo;
import cc.linker.steplink.crm.merchanth5.service.MaiBaoLaService;
import cc.linker.steplink.crm.merchanth5.service.acs.H5RechargeService;
import cc.linker.steplink.crm.merchanth5.service.acs.ProtectRecordService;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessService;
import cc.linker.steplink.crm.response.GlobalException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class H5RechargeServiceImpl implements H5RechargeService {

    // 调用返回结果
    public static final String CREATE_RECHARGE_RESULT = "ACS:CREATE_RECHARGE_RESULT";
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private H5RechargeDao h5RechargeDao;
    @Autowired
    private MaiBaoLaService maiBaoLaService;
    @Autowired
    private PurchaseProcessDao purchaseProcessDao;
    @Autowired
    private WcPayProperties wcPayProperties;
    @Autowired
    private HttpService httpService;
    @Autowired
    private ProtectRecordService protectRecordService;
    @Autowired
    private PurchaseProcessService purchaseProcessService;
    @Autowired
    private SystemProperties systemProperties;

    @Override
    public Map getRechargeInfo(String rechargeSn) {
        return h5RechargeDao.getRechargeInfo(rechargeSn);
    }

    @Override
    public Map rechargeByRechargeSn(Map<String, Object> param) {
        String res = "";
        String rechargeSn = param.get("rechargeSn").toString();
        String customerId = param.get("customerId").toString();
        String orgId = param.get("orgId").toString();
        Map<String, Object> rechargeParam = h5RechargeDao.getRechargeInfo(rechargeSn);
        String customerIdR = rechargeParam.get("customerId").toString();
        String s = stringRedisTemplate.opsForValue().get(CREATE_RECHARGE_RESULT + rechargeSn);
        String openid = (String) param.get("openid");
        Integer payMode = Integer.valueOf(param.get("payMode").toString());
        String payType = "WX";
        if (!StringUtils.isEmpty(s)) {
            LOGGER.info("已经有签名=====");
            // 已生成签名
            res = s;
        } else {
            if (payMode == 2 || payMode == 3) {
                String uId = "";
                if (customerIdR.equals(orgId)) {
                    uId = purchaseProcessDao.getAccountUidByOrgId(orgId);
                } else {
                    uId = purchaseProcessDao.getAccountUidByCustomerId(customerIdR);
                }
                // tl
                param.put("openId", openid);
                param.put("customerId", customerId);
                param.put("orgId", orgId);
                maiBaoLaService.checkCustomerAccount(param, payMode);
                res = this.getSign(uId, orgId, rechargeSn, customerId, openid, payMode, payType);
            }
        }
        Map result = (Map) JSON.parse(res);
        result.put("rechargeSn", rechargeSn);
//        LOGGER.info("请求签名3");
        return result;
    }

    private String getSign(String uId, String orgId, String rechargeSn, String customerId, String openid, Integer payMode, String payType) {
        // 余额支出账户(现金分入账户，推荐费，服务费，大b抽成，联汇抽成)
        String feeId = this.getCustomerIdByFeeTypeAndOrdId(FeeConstants.SERVICE_FEE, orgId, payMode);
        // 收款人id 收款人银行账号 金额 备注 订单sn
        // 支付用户ID
        Map reqMap = new HashMap();
        reqMap.put("customerId", customerId);
        // 商品描述
        reqMap.put("goodsName", "");
        // 支付用户OPENID
        reqMap.put("openID", openid);
        // 平台订单ID
        reqMap.put("orderSn", rechargeSn);
        // 收款用户ID
        reqMap.put("payeeUserID", uId);
        // 余额支出账户
        reqMap.put("feeCustomerId", feeId);
        // 应用appId
        String appId = "";
        if (payMode == 2) {
            appId = stringRedisTemplate.opsForValue().get("appIdWX:_orgId_" + orgId);
            if (StringUtils.isEmpty(appId)) {
                appId = purchaseProcessDao.getAppIdByOrgId(orgId);
                stringRedisTemplate.opsForValue().set("appIdWX:_orgId_" + orgId, appId);
            }
        } else if (payMode == 3) {
            appId = stringRedisTemplate.opsForValue().get("appIdWX:_orgId_linker");
            if (StringUtils.isEmpty(appId)) {
                appId = purchaseProcessDao.getAppIdByOrgId("linker");
                stringRedisTemplate.opsForValue().set("appIdWX:_orgId_linker", appId);
            }
        }
        if (StringUtils.isEmpty(appId)) {
            throw GlobalException.build("appId获取失败");
        }
        reqMap.put("appId", appId);
        // 行业代码
        String industryCode = purchaseProcessDao.getOrgMerchantInfoByOrgId(orgId);
        reqMap.put("industryCode", industryCode);
        // 行业名称
        String industryName = purchaseProcessDao.getIndustryNameByCode(industryCode);
        reqMap.put("industryName", industryName);
        // 支付方式：WX-公众号支付；XCX-微信小程序支付
        reqMap.put("payType", payType);
        // 访问终端类型:1手机；2PC
        reqMap.put("source", 1);
        // 交易验证方式：0-无验证；1-短信验证码；2-支付密码
        reqMap.put("validateType", 0);
        // 测试环境用yt
        String alias = "";
        if (payMode == 3) {
            alias = stringRedisTemplate.opsForValue().get("alias:orgId_linker");
            if (StringUtils.isEmpty(alias)) {
                alias = maiBaoLaService.getAliasByLinker();
                stringRedisTemplate.opsForValue().set("alias:orgId_linker", alias);
            }
        }
        if (payMode == 2) {
            alias = stringRedisTemplate.opsForValue().get("alias:orgId_" + orgId);
            if (StringUtils.isEmpty(alias)) {
                alias = maiBaoLaService.getAlias(orgId);
                stringRedisTemplate.opsForValue().set("alias:orgId_" + orgId, alias);
            }
        }
        reqMap.put("clintType", alias);
        // 手续费
        reqMap.put("fee", 0);
        String notifyUrl = systemProperties.getScrmUrl() + "/h5/recharge/ordernotify";
        reqMap.put("notifyUrl", notifyUrl);
        String url = wcPayProperties.getAcsurl() + WcPayConstant.TRADE_PAY_ORDER;
        // 请求支付网关
        String result = "";
        try {
            LOGGER.info("通联支付请求参数==={}", JSON.toJSONString(reqMap));
            result = httpService.doPost(url, JSON.toJSONString(reqMap), WcPayConstant.JSON);
            result = this.callResultProcess(result);
            stringRedisTemplate.opsForValue().set("orderType_" + rechargeSn, "6", 1, TimeUnit.HOURS);
        } catch (Exception e) {
            LOGGER.error("支付网关调用异常", e);
            throw GlobalException.build("支付网关调用异常");
        }
        return result;
    }

    /**
     * 根据机构和费用类型查询分账配置账号id
     *
     * @param type  见FeeConstants
     * @param orgId 机构id
     */
    @Override
    public String getCustomerIdByFeeTypeAndOrdId(String type, String orgId, Integer payMode) throws GlobalException {

        String account = stringRedisTemplate.opsForValue().get("accountType:type_" + type + "orgId_" + orgId);
        if (StringUtils.isEmpty(account)) {
            account = purchaseProcessDao.getAccountByFeeTypeAndOrdId(type, orgId);
            if (StringUtils.isEmpty(account)) {
                purchaseProcessDao.insertAcsOrgDefaultConfig(orgId);
                account = purchaseProcessDao.getAccountByFeeTypeAndOrdId(type, orgId);
            }
            stringRedisTemplate.opsForValue().set("accountType:type_" + type + "_orgId_" + orgId, account);
        }
        switch (account) {
            case "A":
                String linkId = "";
                if (payMode == 2) {
                    linkId = stringRedisTemplate.opsForValue().get("linkIdType:orgId_" + orgId);
                    if (StringUtils.isEmpty(linkId)) {
                        linkId = purchaseProcessDao.getLinkIdByOrgId(orgId);
                        stringRedisTemplate.opsForValue().set("linkIdType:orgId_" + orgId, linkId);
                    }
                } else if (payMode == 3) {
                    linkId = stringRedisTemplate.opsForValue().get("linkIdType:orgId_linker");
                    if (StringUtils.isEmpty(linkId)) {
                        linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
                        stringRedisTemplate.opsForValue().set("linkIdType:orgId_linker", linkId);
                    }
                }
                if (StringUtils.isEmpty(linkId)) {
                    throw GlobalException.build("联汇暂未开户");
                }
                return linkId;
            case "B":
                String orgUid = stringRedisTemplate.opsForValue().get("orgUid:" + orgId);
                if (StringUtils.isEmpty(orgUid)) {
                    orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
                    stringRedisTemplate.opsForValue().set("orgUid:" + orgId, orgUid);
                }
                if (StringUtils.isEmpty(orgUid)) {
                    throw GlobalException.build("机构暂未开户");
                }
                return orgUid;
            case "C":
                // 平台营销资金账户
                return "#yunBizUserId_B2C#";
            default:
                throw GlobalException.build("机构账户配置错误！");
        }
    }

    /**
     * 调用结果处理(中金)
     */
    @Override
    public String callResultProcess(String result) throws GlobalException {
        if (StringUtils.isEmpty(result)) {
            throw GlobalException.build("网关调用失败");
        }
        LOGGER.info(result);
        Map resMap = (Map) JSON.parse(result);
        if (!resMap.containsKey("code")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        if (!"200".equals(resMap.get("code"))) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        if (!resMap.containsKey("data")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        Map data = (Map) resMap.get("data");
        if (!data.containsKey("authCode")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        return (String) data.get("authCode");
    }

    @Override
    public void callback(Map<String, Object> param) {
        String tradeSn = "";
        String rechargeSn = "";
        if (!StringUtils.isEmpty(param.get("tradeSn"))) {
            tradeSn = param.get("tradeSn").toString();
        }
        if (!StringUtils.isEmpty(param.get("rechargeSn"))) {
            rechargeSn = param.get("rechargeSn").toString();
        } else {
            LOGGER.info("回调参数错误！");
            return;
        }
        h5RechargeDao.updateStatus(param);
        String customerId = h5RechargeDao.getCustomerIdByRechargeSn(rechargeSn);
        if (StringUtils.isEmpty(customerId)) {
            LOGGER.info("充值人为空");
            return;
        }
        //根据orderSn修改金额并下发
        String orderSns = h5RechargeDao.getOrderSns(rechargeSn);
        if (!StringUtils.isEmpty(orderSns)) {
            String[] orderSnList = orderSns.split(",");
            for (String orderSn : orderSnList) {
                //修改充值金额
                Map<String, String> map = h5RechargeDao.getLossMap(orderSn);
                if (customerId.equals(map.get("lossOrgId"))) {
                    h5RechargeDao.updateMallsRecharge(orderSn);
                }
                if (customerId.equals(map.get("lossSalerOrgId"))) {
                    h5RechargeDao.updateSalerRecharge(orderSn);
                }
                Integer isEndCount = h5RechargeDao.isEnd(orderSn);
                if (isEndCount > 0) {
                    this.updateAccountMoney(orderSn);
                }
            }
        }
    }

    @Override
    public void updateAccountMoney(String orderSn) {
        String str[] = orderSn.split(",");
        List<String> orderSnList = Arrays.asList(str);
        for (String orderSno : orderSnList) {
            LOGGER.info("亏损订单入账开始 orderSn--->" + orderSno);
            List<ProtectPo> protectList = protectRecordService.settleOrder(orderSno);
            if (protectList != null && protectList.size() > 0) {
                protectRecordService.insertOldTrder(protectList);
                //更新新表的isEnd状态
                LOGGER.info("亏损订单入账完成 orderSn--->" + orderSno);
                protectRecordService.updateIsEnd(orderSno, 1);
                protectRecordService.updateOrderIsEnd(orderSno, 1);
            } else {
                //更新新表的isEnd状态
                protectRecordService.updateIsEnd(orderSno, 2);
                protectRecordService.updateOrderIsEnd(orderSno, 1);
            }

        }
        // 需要查出开通和报名
        // 查询交易记录今天解冻记录的人与钱(orderSn)
        List<H5UserAccountPo> accountListOrder = h5RechargeDao.selectUnfreezeUserListByOrderSn(orderSn);
        if (accountListOrder != null && accountListOrder.size() > 0) {
            // 通知通联金额下发
            this.beforeAgentPay(accountListOrder);
            // 更新用户账单
            StringBuilder accountSb = new StringBuilder();
            for (H5UserAccountPo userAccountPo : accountListOrder) {
                if (userAccountPo.getType().equals(TradeTypeConstants.TRADE_SERVER_FEE)
                        || userAccountPo.getType().equals(TradeTypeConstants.REJUVENATE_FEE)
                        || userAccountPo.getType().equals(TradeTypeConstants.PURCHASE_FEE)
                        || userAccountPo.getType().equals(TradeTypeConstants.SPREAD_FEE)) {
                    //交易手续费,返润佣金 要扣除余额（冻结金额没有加），采购要减,推广佣金
                    LOGGER.info("交易类型：" + userAccountPo.getType() + "  交易角色：" + userAccountPo.getPayRole());
                    if (userAccountPo.getPayRole() == 1) {
                        h5RechargeDao.reduceOrgAccountInfoByOrgId(userAccountPo);
                    } else if (userAccountPo.getPayRole() == 2) {
                        // 小B
                        h5RechargeDao.reduceXbAccountInfoByCid(userAccountPo);
                        stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                    }
                }
                if (userAccountPo.getReceiveRole() == 1) {
                    h5RechargeDao.updateOrgAccountInfoByOrgId(userAccountPo);
                } else if (userAccountPo.getReceiveRole() == 2) {
                    // 小B
                    h5RechargeDao.updateXbAccountInfoByCid(userAccountPo);
                    stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                } else if (userAccountPo.getReceiveRole() == 4) {
                    // 推广员
                    h5RechargeDao.updateAgentAccountInfoByCid(userAccountPo);
                    stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                } else if (userAccountPo.getReceiveRole() == 5) {
                    // 个人
                    h5RechargeDao.updateAccountInfoByCid(userAccountPo);
                    stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                } else {
                    LOGGER.warn("无需解冻" + userAccountPo);
                }
                accountSb.append(userAccountPo.getId());
                accountSb.append(",");
            }
            LOGGER.info("thawMoney" + accountListOrder);
            //更新账单状态
            h5RechargeDao.updateTradeInfoThawStatus(accountSb.toString());
        } else {
            LOGGER.info("没有需要解冻的金额");
        }
        // 需要查出开通和报名
        // 积分解冻
        List<H5UserAccountPo> scoreUserList = h5RechargeDao.selectUnfreezeScoreUserListByOrderSn(orderSn);
        if (scoreUserList != null && scoreUserList.size() > 0) {
            StringBuilder scoreSb = new StringBuilder();
            for (H5UserAccountPo userAccountPo : scoreUserList) {
                if (userAccountPo.getType() == 1) {
                    // 积分解冻
                    h5RechargeDao.unfreezeScoreByCid(userAccountPo);
                } else if (userAccountPo.getType() == 0) {
                    // 积分购买商品，解冻余额
                    if (userAccountPo.getReceiveRole() == 1) {
                        // 大B
                        h5RechargeDao.updateOrgAccountInfoByOrgId(userAccountPo);
                    } else if (userAccountPo.getReceiveRole() == 2) {
                        // 小B
                        h5RechargeDao.updateXbAccountInfoByCid(userAccountPo);
                        stringRedisTemplate.delete("home:customer_info_" + userAccountPo.getCustomerId());
                    }
                }
                scoreSb.append(userAccountPo.getId());
                scoreSb.append(",");
            }
            LOGGER.info("thawScore" + scoreUserList);
            h5RechargeDao.updateTradeScoreInfoThawStatus(scoreSb.toString());
        } else {
            LOGGER.info("没有需要解冻的积分");
        }
    }

    @Override
    public void beforeAgentPay(List<H5UserAccountPo> accountList) {
        List<String> collect = this.getOrderSn(accountList);
        String join = org.apache.commons.lang.StringUtils.join(collect, ",");
        purchaseProcessService.signalAgentPay(join, "");
    }

    private List<String> getOrderSn(List<H5UserAccountPo> accountList) {
        return accountList.stream()
                .map(x -> x.getOrderSn().split(","))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
    }
}
